package com.ywk.mapperRegister.core.scanRegister;

import com.ywk.mapperRegister.core.DBMapperFactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;

import java.util.Set;

/**
 * 通过扫描 @MapperScan 注解包下的文件动态生成代理接口 bean（此类使用的方式）
 *
 * @Author zbh
 * @Date 2023/5/9
 */
public class DBClassPathMapperScanner extends ClassPathBeanDefinitionScanner {

    public DBClassPathMapperScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }

    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        //使用父类的方法扫描指定的包路径，返回的 beanDefinitions 已经在容器当中
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        //添加自定义逻辑处理 beanDefinition
        processBeanDefinitions(beanDefinitions);

        return beanDefinitions;
    }

    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        AbstractBeanDefinition definition;
        for (BeanDefinitionHolder holder : beanDefinitions) {
            definition = (AbstractBeanDefinition) holder.getBeanDefinition();
            //获取 mapper Class
            String beanClassName = definition.getBeanClassName();
            //将definition的类型改为 DBMapperFactoryBean，自定义的 FactoryBean
            definition.setBeanClass(DBMapperFactoryBean.class);
            //设置 bean实例化时使用的构造方法，传入对应参数
            definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);

        }
    }

    // 我们只关心接口，所以重写时要覆盖Spring的默认规则
    @Override
    public boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        //spring 默认是会排除接口，所以需要重写该方法让它能扫描到接口进行注册 beanDefinition
        return beanDefinition.getMetadata().isInterface();
    }
}
